/// @tags: SAM
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>

using namespace std;

namespace BlueQuantum {

int const N = 2e5 + 5, M = 26;

char s[N];
int n, tot = 1, lst = 1, ans, e_cnt, cnt;
int ch[N * 2][M], len[N * 2], link[N * 2], pos[N * 2], rt[N * 2], dp[N * 2], fr[N * 2],
    heads[N * 2];

struct Node {
  int ls, rs;
} t[N * 40];

struct Edge {
  int v, nxt;
} e[N * 2];

inline void add(int u, int v) {
  e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt;
}

void modify(int &x, int l, int r, int p) {
  if (!x) x = ++cnt;
  if (l == r) return;
  int mid = (l + r) >> 1;
  p <= mid ? modify(t[x].ls, l, mid, p) : modify(t[x].rs, mid + 1, r, p);
}

int merge(int x, int y) {
  if (!(x && y)) return x | y;
  int res = ++cnt;
  t[res].ls = merge(t[x].ls, t[y].ls);
  t[res].rs = merge(t[x].rs, t[y].rs);
  return res;
}

bool query(int u, int l, int r, int L, int R) {
  if (!u || l > R || r < L) return false;
  if (l >= L && r <= R) return true;
  int mid = (l + r) >> 1;
  return query(t[u].ls, l, mid, L, R) || query(t[u].rs, mid + 1, r, L, R);
}

inline void extend(int c, int id) {
  int cur = ++tot, p = lst;
  lst = cur;
  len[cur] = len[p] + 1;
  pos[cur] = id;
  while (p != 0 && ch[p][c] == 0) ch[p][c] = cur, p = link[p];
  if (p == 0) return link[cur] = 1, modify(rt[cur], 1, n, id);
  int q = ch[p][c];
  if (len[q] == len[p] + 1) return link[cur] = q, modify(rt[cur], 1, n, id);
  int clone = ++tot;
  memcpy(ch[clone], ch[q], sizeof(ch[q]));
  link[clone] = link[q];
  link[q] = link[cur] = clone;
  len[clone] = len[p] + 1;
  pos[clone] = pos[q];
  while (p != 0 && ch[p][c] == q) ch[p][c] = clone, p = link[p];
  modify(rt[cur], 1, n, id);
}

void dfs(int u) {
  for (int i = heads[u]; i; i = e[i].nxt) {
    dfs(e[i].v);
    rt[u] = merge(rt[u], rt[e[i].v]);
  }
}

void solve(int u) {
  for (int i = heads[u], v; i; i = e[i].nxt) {
    v = e[i].v;
    if (u == 1) {
      fr[v] = v, dp[v] = 1;
    } else if (query(rt[fr[u]], 1, n, pos[v] - len[v] + len[fr[u]], pos[v] - 1)) {
      dp[v] = dp[u] + 1;
      fr[v] = v;
    } else {
      dp[v] = dp[u];
      fr[v] = fr[u];
    }
    solve(v);
  }
  ans = max(ans, dp[u]);
}

inline int main() {
  cin >> n >> (s + 1);
  for (int i = 1; i <= n; ++i) extend(s[i] - 'a', i);
  for (int i = 2; i <= tot; ++i) add(link[i], i);
  dfs(1);
  solve(1);
  cout << ans;
  return 0;
}

}  // namespace BlueQuantum

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("CF700E Cool Slogans.in", "r", stdin);
  freopen("CF700E Cool Slogans.out", "w", stdout);
#endif
#endif

  ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  return BlueQuantum::main();
}
